﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using XCI.Excel;
using XCI.Extensions;
using XCI.Helper;
using XCI.Service;
using XCI.Setting;
using XCI.Windows;

namespace XCI.Core
{
    /// <summary>
    /// 应用处理器
    /// </summary>
    public class AppHandler
    {
        private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
        private JsonFile<AppSetting> appSettingJsonFile;

        /// <summary>
        /// 加载应用配置
        /// </summary>
        public virtual AppSetting LoadAppSetting()
        {
            if (appSettingJsonFile == null) appSettingJsonFile = GetAppSettingJsonFile();
            return appSettingJsonFile.Data;
        }

        /// <summary>
        /// 保存应用配置
        /// </summary>
        public virtual void SaveAppSetting()
        {
            if (appSettingJsonFile == null) appSettingJsonFile = GetAppSettingJsonFile();
            var setting = JsonHelper.GetDefaultSetting(Formatting.Indented);
            setting.NullValueHandling = NullValueHandling.Ignore;
            appSettingJsonFile.Save(setting);
        }

        /// <summary>
        /// 获取应用配置文件对象
        /// </summary>
        protected virtual JsonFile<AppSetting> GetAppSettingJsonFile()
        {
            var filePath = IOHelper.GetRootFilePath("app.json");
#if DEBUG
            var debugFilePath = IOHelper.GetRootFilePath("app.debug.json");
            if (File.Exists(debugFilePath))
            {
                filePath = debugFilePath;
            }
#endif
            return new JsonFile<AppSetting>(filePath);
        }

        /// <summary>
        /// 获取闪屏类型
        /// </summary>
        public virtual Type GetSplashScreenType()
        {
            return typeof(FrmSplashScreen);
        }

        /// <summary>
        /// 获取等待窗体类型
        /// </summary>
        public virtual Type GetWaitFormType()
        {
            return typeof(FrmWait);
        }

        /// <summary>
        /// 全局未处理异常处理
        /// </summary>
        /// <param name="e">未处理异常对象</param>
        public virtual void OnGlobalExceptionHandler(Exception e)
        {
            if (e is WebApiClientBoolResultException webApiClientBoolResultException)
            {
                var apiResult = webApiClientBoolResultException.Result;
                if (apiResult.Fail && !string.IsNullOrEmpty(apiResult.Msg))
                {
                    MessageBoxHelper.ShowError(apiResult.Msg);
                }
                return;
            }
            if (e is ModelValidatorException modelValidatorException)
            {
                var validResult = modelValidatorException.Result;
                var errorMsg = MergeValidationResult(validResult);
                if (!string.IsNullOrEmpty(errorMsg))
                {
                    MessageBoxHelper.ShowWarn(errorMsg);
                }
                return;
            }
            if (e is TaskCanceledException taskCanceledException)
            {
                Logger.Error(taskCanceledException);
                return;
            }

            if (App.Setting.DebugMode)
            {
                var form = new FrmException(e);
                form.ShowDialog();
                form.Dispose();
            }
            else
            {
                Logger.Error(e, "请注意：有未处理异常：");
            }
        }

        /// <summary>
        /// 创建应用服务器对象
        /// </summary>
        public virtual WebApiClient CreateWebApiClient(WebApiConfig config)
        {
            return new WebApiClient(config);
        }

        /// <summary>
        /// 创建文件应用服务器对象
        /// </summary>
        public virtual WebApiClient CreateFileWebApiClient(WebApiConfig config)
        {
            return new WebApiClient(config);
        }

        /// <summary>
        /// 创建配置存储对象
        /// </summary>
        public virtual ISettingStore CreateSettingStore()
        {
            return new ServerSettingStore();
        }

        /// <summary>
        /// 创建模型验证器
        /// </summary>
        public virtual ModelValidator CreateValidator()
        {
            return new ModelValidator();
        }

        /// <summary>
        /// 创建容器数据操作器
        /// </summary>
        public virtual ContainerData CreateContainerForm()
        {
            return new ContainerData();
        }

        /// <summary>
        /// 创建Excel导入导出对象
        /// </summary>
        public virtual ExcelData CreateExcel()
        {
            return new ExcelData();
        }

        /// <summary>
        /// 创建启动窗体
        /// </summary>
        public virtual Form OnCreateStartupForm()
        {
            return new BaseForm();
        }

        /// <summary>
        /// 应用初始化回调函数
        /// </summary>
        public virtual void OnApplicationInit()
        {

        }

        /// <summary>
        /// 应用退出回调函数
        /// </summary>
        public virtual void OnApplicationExit()
        {

        }

        /// <summary>
        /// 同步日期时间
        /// </summary>
        /// <param name="messageCallback">消息回调</param>
        public virtual void SyncDateTime(MessageCallback messageCallback)
        {
            try
            {
                messageCallback?.Invoke("正在同步日期时间...");
                var result = AsyncHelper.RunSync(() => CoreService.Instance.DatetimeAsync());
                if (DateTime.TryParse(result, out var dt))
                {
                    NativeMethods.SetLocalDateTime(dt);
                }
            }
            catch (Exception e)
            {
                messageCallback?.Invoke("同步日期时间失败");
                Logger.Error(e, "同步日期时间失败");
            }
        }

        /// <summary>
        /// 更新应用程序
        /// </summary>
        /// <param name="messageCallback">消息回调</param>
        public virtual void Upgrade(MessageCallback messageCallback)
        {
            try
            {
                messageCallback?.Invoke("正在检查更新...");
                var packageList = AsyncHelper.RunSync(() => App.FileClient.PostAsync<List<UpgradePackageInfo>>("/upgrade/check", new { version = GetLocalVersion() }));
                if (packageList == null || packageList.Count == 0) return;
                var plist = new List<string>();
                foreach (UpgradePackageInfo item in packageList)
                {
                    messageCallback?.Invoke($"正在下载更新包{item.Version}...");
                    var packagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, item.Name);

                    try
                    {
                        AsyncHelper.RunSync(() => App.FileClient.DownloadAsync(new WebApiDownloadOption
                        {
                            Url = item.Url,
                            SaveFilePath = packagePath,
                            Method = HttpMethod.Get,
                            ContentType = WebApiContentType.None,
                            Log = new WebApiLogConfig { EnableRequestLog = true, EnableResponseStatusLog = true, EnableResponseContentLog = true }
                        }));
                        plist.Add($"{item.Name}:{item.Version}");
                    }
                    catch(Exception ex)
                    {
                        Logger.Error(ex, "软件升级出错,Url={0},LocalPath={1}", item.Url,packagePath);
                    }
                }
                messageCallback?.Invoke("正在应用升级包...");
                Startup.Upgrade(plist.JoinString());
            }
            catch
            {
                messageCallback?.Invoke("软件升级失败");
            }
        }

        private static string GetLocalVersion()
        {
            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "version.ini");
            var version = "0";
            if (File.Exists(path)) version = File.ReadAllText(path, Encoding.UTF8);
            if (string.IsNullOrWhiteSpace(version)) version = "0";
            return version;
        }

        /// <summary>
        /// 应用单实例启动时异常处理
        /// </summary>
        public virtual void OnSingletonExceptionHandler()
        {
            var msg = string.Empty;
            if (App.Setting.DebugMode) msg = "已经有一个客户端程序在运行了,一台计算机上不能同时运行多个客户端";
            if (!string.IsNullOrWhiteSpace(msg))
            {
                MessageBox.Show(msg, "系统启动警告", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
            }
        }

        /// <summary>
        /// 获取数据字典
        /// </summary>
        /// <param name="code">字典编码</param>
        /// <returns>返回指定编码的数据字典</returns>
        public virtual Dic GetDic(string code)
        {
            return new Dic(code, new List<DicItem>());
        }

        /// <summary>
        /// 格式化验证错误消息
        /// </summary>
        /// <param name="validationResults">验证错误结果集合</param>
        /// <returns>返回格式化后的错误消息</returns>
        public virtual string FormatValidateErrorMessage(ICollection<ValidationResult> validationResults)
        {
            return MergeValidationResult(validationResults);
        }

        /// <summary>
        /// 合并验证消息
        /// </summary>
        /// <param name="results">验证结果列表</param>
        private string MergeValidationResult(ICollection<ValidationResult> results)
        {
            if (results == null || results.Count == 0) return string.Empty;
            var i = 0;
            StringBuilder msg = new StringBuilder();
            foreach (var item in results)
            {
                msg.AppendLine(item.ErrorMessage);
                i++;
                if (i > AppDefaultSettings.ValidationResultMergeMaxCount)
                {
                    break;
                }
            }
            return msg.ToString();
        }

        /// <summary>
        /// 是否有指定模块编码的权限
        /// </summary>
        /// <param name="codes">模块编码集合</param>
        /// <returns>存在返回true,否则返回false</returns>
        public virtual bool Permit(params string[] codes)
        {
            return true;
        }

    }
}